package cn.fintecher.pangolin.service.business.web;

import cn.fintecher.pangolin.common.enums.BaseSelect;
import cn.fintecher.pangolin.common.response.LoginResponse;
import cn.fintecher.pangolin.common.utils.BeanUtils;
import cn.fintecher.pangolin.common.web.BaseController;
import cn.fintecher.pangolin.entity.elastic.PaymentRecord;
import cn.fintecher.pangolin.entity.mysql.CaseInfo;
import cn.fintecher.pangolin.entity.mysql.QCaseInfo;
import cn.fintecher.pangolin.service.business.model.request.DebtMessageRequest;
import cn.fintecher.pangolin.service.business.model.request.PaymentRecordRequest;
import cn.fintecher.pangolin.service.business.model.response.PaymentRecordResponse;
import cn.fintecher.pangolin.service.business.repository.elasticsearch.PaymentRecordElastic;
import cn.fintecher.pangolin.service.business.repository.jparepository.CaseInfoRepository;
import cn.fintecher.pangolin.service.business.service.BaseService;
import cn.fintecher.pangolin.service.business.service.PaymentRecordService;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import io.swagger.annotations.*;
import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @Auther: xiaqun
 * @Description: 还款记录相关接口
 * @Date: 14:50 2019/10/11
 */

@RestController
@RequestMapping("/api/paymentRecordController")
@Api(value = "还款记录相关接口", description = "还款记录相关接口")
public class PaymentRecordController extends BaseController {

    @Autowired
    private BaseService baseService;

    @Autowired
    private PaymentRecordService paymentRecordService;

    @Autowired
    private CaseInfoRepository caseInfoRepository;
    @Autowired
    private PaymentRecordElastic paymentRecordElastic;

    /**
     * 查询还款记录
     */
    @ApiOperation(value = "查询还款记录", notes = "查询还款记录")
    @GetMapping("/findPaymentRecord")
    public ResponseEntity<List<PaymentRecordResponse>> findPaymentRecord(@RequestParam @ApiParam(value = "案件ID") String caseId) {
        log.info("REST request to find payment record,{}", caseId);
        List<PaymentRecordResponse> list = paymentRecordService.findPaymentRecord(caseId);
        return ResponseEntity.ok().body(list);
    }


    /**
     * @Author wangxiangdong
     * @Description 查询共债对账信息
     * @Date 2019/10/28 15:56
     **/
    @ApiOperation(value = "查询共债对账信息", notes = "查询共债对账信息")
    @GetMapping("/caseBillRecord")
    public ResponseEntity<List<PaymentRecordResponse>> caseBillRecord(DebtMessageRequest debtMessageRequest,
                                                                      @RequestHeader(value = "X-UserToken") String token) {
        List<PaymentRecordResponse> list = paymentRecordService.caseBillRecord(debtMessageRequest, token);
        return ResponseEntity.ok().body(list);
    }

    @ApiOperation(value = "查询对账列表", notes = "查询对账列表")
    @GetMapping("/findAllPaymentRecords")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", dataType = "int", paramType = "query",
                    value = "页数 (0..N)"),
            @ApiImplicitParam(name = "size", dataType = "int", paramType = "query",
                    value = "每页大小."),
            @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query",
                    value = "依据什么排序: 属性名(,asc|desc). ")
    })
    public ResponseEntity<Page<PaymentRecordResponse>> findAllPaymentRecords(PaymentRecordRequest request, @RequestHeader(value = "X-UserToken") String token, Pageable pageable) {
        LoginResponse userSessionByToken = baseService.getUserSessionByToken(token);
        BooleanBuilder booleanBuilder = request.generateBooleanBuilder();
        if (Objects.equals(userSessionByToken.getUserModel().getIsManage(), BaseSelect.YES)) {
            booleanBuilder.and(QCaseInfo.caseInfo.currentCollector.department.departCode.like(StringUtils.join(userSessionByToken.getDepartmentModel().getDepartCode(), "%")));
        } else {
            booleanBuilder.and(QCaseInfo.caseInfo.currentCollector.id.eq(userSessionByToken.getUserModel().getId()));
        }
        List<CaseInfo> caseInfoList = IterableUtils.toList(caseInfoRepository.findAll(booleanBuilder));
        Map<String, CaseInfo> baseCaseMap = caseInfoList.stream().collect(Collectors.toMap(CaseInfo::getId, caseInfo -> caseInfo));
        List<String> caseIds = caseInfoList.stream().map(CaseInfo::getId).collect(Collectors.toList());
        List<List<String>> idsList = Lists.partition(caseIds, 1000);
        List<String> paymentRecordCaseIds = new ArrayList<>();
        for (List<String> ids : idsList) {
            BoolQueryBuilder paymentQueryBuilder = request.generateBillQueryBuilder();
            paymentQueryBuilder.must(termsQuery("caseId.keyword", ids));
            List<PaymentRecord> paymentRecords = Lists.newArrayList(paymentRecordElastic.search(paymentQueryBuilder));
            if (paymentRecords.size() > 0) {
                paymentRecordCaseIds.addAll(paymentRecords.stream().map(PaymentRecord::getCaseId).collect(Collectors.toList()));
            }
        }
        BoolQueryBuilder queryBuilder = request.generateBillQueryBuilder();
        queryBuilder.must(termsQuery("caseId.keyword", paymentRecordCaseIds));
        SortBuilder sortBuilder = SortBuilders.fieldSort("paymentDate").unmappedType("date").order(SortOrder.DESC);
        SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(queryBuilder).withPageable(pageable).withSort(sortBuilder).build();
        Page<PaymentRecordResponse> page = paymentRecordElastic.search(searchQuery).map(payAmtLog -> {
            PaymentRecordResponse recordResponse = new PaymentRecordResponse();
            CaseInfo caseInfo = baseCaseMap.get(payAmtLog.getCaseId());
            BeanUtils.copyProperties(caseInfo, recordResponse);
            if (Objects.nonNull(caseInfo.getCurrentCollector())) {
                recordResponse.setCollectorUsername(caseInfo.getCurrentCollector().getRealName());
                recordResponse.setDepartmentName(caseInfo.getCurrentCollector().getDepartment().getName());
            }
            if (Objects.nonNull(caseInfo.getDepartment())) {
                recordResponse.setDepartmentName(caseInfo.getDepartment().getName());
            }
            recordResponse.setId(payAmtLog.getId());
            recordResponse.setCaseId(caseInfo.getId());
            recordResponse.setBillType(payAmtLog.getBillType());
            recordResponse.setPaymentAmt(payAmtLog.getPaymentAmt());
            recordResponse.setPaymentDate(payAmtLog.getPaymentDate());
            recordResponse.setRemark(payAmtLog.getRemark());
            return recordResponse;
        });
        return ResponseEntity.ok().body(page);
    }
}
